1 import java.util.*;
2 import java.io.*;
3
4 public class Controller extends Thread {
5
6 private static final int sleepPeriod = 800;
7 private static final int idlePeriod = 250;
8 private static final int stateNEW = 0;
9 private static final int stateREADY = 1;
10 private static final int stateRUNNING = 2;
11 private static final int statePAUSED = 3;
12 private static final int statePENDING = 4;
13 private static final int stateSTOPPED = 5;
14
15 private static final int slaveDISABLED = 0;
16 private static final int slaveDOWN = 1;
17 private static final int slaveLOADED = 2;
18 private static final int slaveTARGETED = 3;
19 private static final int slaveUP = 4;
20 private static final int slaveBAD = 5;
21
22 private static final int runNOT = 0;
23 private static final int runRUNNING = 1;
24 private static final int runDONE = 2;
25 private static final int runREPORTED = 3;
26
27 private static final int sessionNameDivisor = 100000;
28 private static final int pingPeriod = 9000;
29 private static final String empty = "...";
30
31 MasterUI myUI;
32
33 MEventQueue myEvents;
34
35 HTTPPush slaves[];
36 MCommandQueue slaveQueues[];
37 int slaveStates[];
38 int runStatus[];
39
40 String sessionNameTag;
41
42 SessionLog log;
43 long lastPing;
44
45 int state = stateNEW;
46
47 MEvent currentEvent;
48
49 public Controller(MasterUI ui) {
50 myUI = ui;
51 this.initialize();
52 }
53
54 protected void initialize() {
55
56 int index;
57
58 myEvents = new MEventQueue();
59 myUI.register(myEvents);
60
61 slaves = new HTTPPush[MasterUI.numberOfSlaves];
62 slaveQueues = new MCommandQueue[MasterUI.numberOfSlaves];
63 slaveStates = new int[MasterUI.numberOfSlaves];
64 runStatus = new int[MasterUI.numberOfSlaves];
65
66 for (index = 0; index < MasterUI.numberOfSlaves; index++) {
67
68 log = new SessionLog();
69
70 slaves[index] = new HTTPPush();
71 slaveQueues[index] = new MCommandQueue();
72
73 slaveStates[index] = slaveDOWN;
74
75 slaves[index].init(slaveQueues[index], log, myEvents, index);
76 slaves[index].start();
77 }
78 }
79
80 public void run() {
81
82 MEvent tempEvent;
83 int index;
84 MCommand aCommand;
85
86 myUI.putScreenLog("Controller UP!");
87 setNew();
88
89 while(true) {
90
91 // Check for events
92 if (myEvents.has() == true) {
93
94 currentEvent = myEvents.get();
95 switch(currentEvent.event) {
96
97 case MEvent.eventUI_STOP:
98 handleStop();
99 break;
100
101 case MEvent.eventUI_START:
102 handleStart();
103 break;
104
105 case MEvent.eventUI_REFRESH:
106 handleRefresh();
107 break;
108
109 case MEvent.eventUI_PAUSE:
110 handlePause();
111 break;
112
113 case MEvent.eventSLAVE_RESPONSE:
114 handleSlave();
115 break;
116
117 case MEvent.eventTIME:
118 // nothin now
119 break;
120
121 case MEvent.eventNULL:
122 default:
123 System.out.println("Software Detected Fault: Controller.run : Unknown event.");
124 break;
125 }
126
127 } else {
128
129 // any run stuff?
130 if (state == stateRUNNING) {
131
132 // Do run stuff. idle breifly at the end.
133 if (checkDone()) {
134
135 myUI.putScreenLog("!DONE! All slaves report done.");
136 tempEvent = new MEvent();
137 tempEvent.event = MEvent.eventUI_STOP;
138 myEvents.put(tempEvent);
139 }
140
141 if ( log.getRaw() > (lastPing + pingPeriod)) {
142
143 for (index = 0; index < MasterUI.numberOfSlaves; index++) {
144
145 if (runStatus[index] == runRUNNING) {
146 aCommand = new MCommand();
147 aCommand.command = MCommand.cmdPING;
148 aCommand.item = empty;
149 slaveQueues[index].put(aCommand);
150 }
151 }
152 lastPing = log.getRaw();
153 }
154
155 try { this.sleep(idlePeriod); } catch (Exception e) { }
156
157 } else {
158
159 // Nuthin' there. sleep
160 try { this.sleep(sleepPeriod); } catch (Exception e) { }
161 }
162 }
163
164 } // end while
165
166 }
167
168 private void handleStop() {
169
170 MCommand aCommand;
171
172 if (state == stateRUNNING) {
173
174 state = statePENDING;
175
176 // Create a session name
177 // send a GO to everyone that is enabled
178 int index;
179 for (index = 0; index < MasterUI.numberOfSlaves; index++) {
180
181 if (myUI.isEnabled(index) == true) {
182 aCommand = new MCommand();
183 aCommand.command = MCommand.cmdSTOP;
184 aCommand.item = empty;
185 slaveQueues[index].put(aCommand);
186 }
187
188 if (myUI.isEnabled(index) == true) {
189 aCommand = new MCommand();
190 aCommand.command = MCommand.cmdGETLOG;
191 aCommand.item = empty;
192 slaveQueues[index].put(aCommand);
193 }
194
195 }
196
197 myUI.putScreenLog("STOP. Session name = " + sessionNameTag);
198
199 } else {
200 myUI.putScreenLog("STOP Rejected. Not running.");
201 }
202
203 }
204
205 private void handleStart() {
206
207 MCommand aCommand;
208
209 // only consider if ready or stopped
210 checkReady();
211 if ((state == stateREADY)||(state == stateSTOPPED)) {
212
213 // Create a session name
214 long name = log.getRaw() / sessionNameDivisor;
215 log.startTiming();
216 sessionNameTag = Long.toString(name);
217
218 // send a GO to everyone that is enabled
219 int index;
220 for (index = 0; index < MasterUI.numberOfSlaves; index++) {
221
222 if (myUI.isEnabled(index) == true) {
223 runStatus[index] = runNOT;
224
225 aCommand = new MCommand();
226 aCommand.command = MCommand.cmdGO;
227 aCommand.item = empty;
228 slaveQueues[index].put(aCommand);
229 }
230 }
231
232 myUI.putScreenLog("START. Session name = " + sessionNameTag);
233
234 } else {
235 myUI.putScreenLog("START Rejected. Not ready.");
236 }
237 }
238
239 private void handleRefresh() {
240
241 int index;
242 MCommand aCommand;
243
244 // If we are running, reject this.
245 if ((state == stateRUNNING)||(state == statePAUSED)) {
246 myUI.putScreenLog("REJECTED REFRESH. Cannot refresh while running.");
247 return;
248 }
249
250 // Ok. Queue up targets and loads for all the enabled slaves.
251 for (index = 0; index < MasterUI.numberOfSlaves; index++) {
252
253 runStatus[index] = runNOT;
254
255 if (myUI.isEnabled(index) == true) {
256
257 aCommand = new MCommand();
258 aCommand.command = MCommand.cmdSET_SLAVE_TARGET;
259 aCommand.item = myUI.getTarget(index);
260 slaveQueues[index].put(aCommand);
261
262 // Stop it just in case.
263 aCommand = new MCommand();
264 aCommand.command = MCommand.cmdSTOP;
265 aCommand.item = myUI.getTarget(index); // just so it isnt empty
266 slaveQueues[index].put(aCommand);
267
268 aCommand = new MCommand();
269 aCommand.command = MCommand.cmdTARGET;
270 aCommand.item = myUI.getTestMachine();
271 slaveQueues[index].put(aCommand);
272
273 // Read the script. if it blows up, forget the whole thing
274 try {
275 FileReader in = new FileReader(myUI.getScript(index));
276 int n;
277 int size;
278 char[] b = new char[1024];
279 StringBuffer buffer = new StringBuffer();
280 while (true) {
281 size = in.read(b, 0, 1024);
282 if (size == -1) break;
283 buffer.append(b, 0, size);
284 }
285 in.close();
286
287 aCommand = new MCommand();
288 aCommand.command = MCommand.cmdNEW;
289 aCommand.value = myUI.getUser(index);
290 aCommand.item = buffer.toString();
291 slaveQueues[index].put(aCommand);
292
293 setSlaveDown(index);
294
295 } catch (FileNotFoundException e) {
296 myUI.putScreenLog("ERROR! Script file not found for slave " + index);
297 setSlaveBad(index);
298 } catch (IOException e) {
299 myUI.putScreenLog("ERROR! Error reading script file for slave " + index);
300 setSlaveBad(index);
301 }
302
303 } else {
304 slaveStates[index] = slaveDISABLED;
305
306 } // end if
307
308 } // end while
309
310 // Ok. now we have to wait.
311 setNew();
312 }
313
314 private void handlePause() {
315
316 }
317
318 private void handleSlave() {
319
320 int id = currentEvent.id;
321
322 // Ignore any responses on a bad slave
323 if (slaveStates[id] == slaveBAD) return;
324
325 // Act according to the original command
326 switch(currentEvent.index) {
327
328 case MCommand.cmdNEW:
329 if (currentEvent.value == MEvent.rSUCCESS) {
330 if (slaveStates[id] == slaveTARGETED) {
331 setSlaveUp(id);
332 checkReady();
333 } else if (slaveStates[id] == slaveDOWN) {
334 slaveStates[id] = slaveLOADED;
335 } else {
336 System.out.println("Software Detected Fault: Controller.handleSlave : Odd state for slave when processing NEW response.");
337 }
338
339 } else {
340 myUI.putScreenLog("!SLAVE ERROR! Couldn't load script on slave " + id);
341 myUI.putScreenLog("---> " + (String)currentEvent.item);
342 setSlaveBad(id);
343 }
344 break;
345
346 case MCommand.cmdTARGET:
347 if (currentEvent.value == MEvent.rSUCCESS) {
348 if (slaveStates[id] == slaveLOADED) {
349 setSlaveUp(id);
350 checkReady();
351 } else if (slaveStates[id] == slaveDOWN) {
352 slaveStates[id] = slaveTARGETED;
353 } else {
354 System.out.println("Software Detected Fault: Controller.handleSlave : Odd state for slave when processing TARGET response.");
355 }
356
357 } else {
358 myUI.putScreenLog("!SLAVE ERROR! Couldn't set target on slave " + id);
359 myUI.putScreenLog("---> " + (String)currentEvent.item);
360 setSlaveBad(id);
361 }
362 break;
363
364 case MCommand.cmdSET_SLAVE_TARGET:
365 // dont do a thing
366 break;
367
368 case MCommand.cmdSTOP:
369 if (currentEvent.value == MEvent.rSUCCESS) {
370 myUI.putScreenLog("STOP. Slave " + id);
371 } else {
372 // Only get pissy if it running
373 if ((state == stateRUNNING)||(state == statePAUSED)) {
374 myUI.putScreenLog("!SLAVE ERROR! Cound not STOP slave " +id);
375 myUI.putScreenLog("---> " + (String)currentEvent.item);
376 setSlaveBad(id);
377 }
378 }
379 break;
380
381 case MCommand.cmdPAUSE:
382 if (currentEvent.value == MEvent.rSUCCESS) {
383 myUI.putScreenLog("PAUSED. Slave " + id);
384 } else {
385 myUI.putScreenLog("!SLAVE ERROR! Cound not PAUSE slave " +id);
386 myUI.putScreenLog("---> " + (String)currentEvent.item);
387 setSlaveBad(id);
388 }
389 break;
390
391 case MCommand.cmdGETLOG:
392 if (currentEvent.value == MEvent.rSUCCESS) {
393
394 // Write the logfile
395 try {
396 FileWriter out = new FileWriter("log-" + sessionNameTag + "-" + currentEvent.id + ".txt");
397 String ts = (String)currentEvent.item;
398 out.write(ts, 0, ts.length());
399 out.close();
400 } catch (Exception e) {
401 myUI.putScreenLog("GETLOG - Error writting logfile for " + "log-" + sessionNameTag + "-" + currentEvent.id + ".txt");
402 }
403 myUI.putScreenLog("GETLOG Successful. Slave " + id);
404 runStatus[id] = runREPORTED;
405
406 } else {
407 myUI.putScreenLog("!SLAVE ERROR! Cound not GO slave " +id);
408 myUI.putScreenLog("---> " + (String)currentEvent.item);
409 setSlaveBad(id);
410 }
411 checkReported();
412 break;
413
414 case MCommand.cmdGO:
415 if (currentEvent.value == MEvent.rSUCCESS) {
416 myUI.putScreenLog("GO Successful. Slave " + id);
417 runStatus[id] = runRUNNING;
418 myUI.setSlaveStatus("RUN", MasterUI.statusGreen, id);
419 checkRunning();
420 } else {
421 myUI.putScreenLog("!SLAVE ERROR! Cound not GO slave " +id);
422 myUI.putScreenLog("---> " + (String)currentEvent.item);
423 setSlaveBad(id);
424 }
425 break;
426
427 case MCommand.cmdPING:
428 if (currentEvent.value == MEvent.rSUCCESS) {
429 // SNARF the status
430 String text = (String)currentEvent.item;
431 int pingStatus = text.indexOf('4'); // is it done?
432 if (pingStatus != -1) {
433 runStatus[id] = runDONE;
434 }
435
436 } else {
437 myUI.putScreenLog("!SLAVE ERROR! Failed PING for " +id);
438 setSlaveBad(id);
439 }
440 break;
441
442 case MCommand.cmdNULL:
443 default:
444 System.out.println("Software Detected Fault: Controller.handleSlave : Unknown command.");
445 break;
446 } // end case
447
448 }
449
450 private void setNew() {
451 state = stateNEW;
452 myUI.setStatus("NEW", MasterUI.statusGray);
453 }
454
455 private void setReady() {
456 state = stateREADY;
457 myUI.setStatus("READY!", MasterUI.statusGreen);
458 }
459
460 private void setRunning() {
461 state = stateRUNNING;
462 myUI.setStatus("RUNNING!", MasterUI.statusGreen);
463 lastPing = log.getRaw();
464 }
465
466 private void setStopped() {
467 state = stateSTOPPED;
468 myUI.setStatus("STOPPED", MasterUI.statusGray);
469 }
470
471 private void setSlaveDown(int slot) {
472 slaveStates[slot] = slaveDOWN;
473 myUI.setSlaveStatus("DOWN", MasterUI.statusOrange, slot);
474 }
475
476 private void setSlaveBad(int slot) {
477 slaveStates[slot] = slaveBAD;
478 myUI.setSlaveStatus("BAD", MasterUI.statusRed, slot);
479 }
480
481 private void setSlaveUp(int slot) {
482 slaveStates[slot] = slaveUP;
483 myUI.setSlaveStatus("UP", MasterUI.statusGreen, slot);
484 }
485
486 private void checkReady() {
487
488 boolean ready = true;
489 int index;
490
491 for (index = 0; index < MasterUI.numberOfSlaves; index++) {
492
493 if ((slaveStates[index] != slaveUP)&&
494 (slaveStates[index] != slaveDISABLED)) ready = false;
495 }
496 if (ready == true) setReady();
497 }
498
499 private boolean checkDone() {
500
501 boolean done = true;
502 int index;
503
504 for (index = 0; index < MasterUI.numberOfSlaves; index++) {
505 if (runStatus[index] == runRUNNING) done = false;
506 }
507 return done;
508 }
509
510 private void checkRunning() {
511
512 boolean run = true;
513 int index;
514
515 for (index = 0; index < MasterUI.numberOfSlaves; index++) {
516
517 if ((runStatus[index] != runRUNNING)&&
518 (slaveStates[index] != slaveDISABLED)&&
519 (slaveStates[index] != slaveBAD)) run = false;
520 }
521 if (run == true) setRunning();
522 }
523
524 private void checkReported() {
525
526 boolean report = true;
527 int index;
528
529 for (index = 0; index < MasterUI.numberOfSlaves; index++) {
530
531 if ((runStatus[index] != runREPORTED)&&
532 (slaveStates[index] != slaveDISABLED)&&
533 (slaveStates[index] != slaveBAD)) report = false;
534 }
535 if (report == true) setStopped();
536 }
537
538
539 }
|